using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace FourBall
{
    public class FourBall : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        SpriteFont font;

        Texture2D rear;
        Texture2D back;
        Texture2D menu;
        Texture2D help;

        Texture2D hl;
        Texture2D red;
        Texture2D blue;
        Texture2D gold;
        Texture2D menuSel;
        Texture2D pause;
        Texture2D orangew;
        Texture2D cyanw;
        Texture2D draw;


        Vector2 posMenuSel = new Vector2(450, 375);
        int menuItem = 0;

        SoundEffect menuSound;

        SoundEffect backSound;
        SoundEffectInstance backSoundInstance;
        SoundEffect selectClmSound;
        SoundEffect shootSound;
        SoundEffect bounceSound;
        SoundEffect pushButton;
        SoundEffect exitZone;
        SoundEffect applause;

        Model cubeModel;
        MyModel cube;
        Vector3 cameraPosition = new Vector3(5.0f, 5.0f, 5.0f);

        KeyboardState k = Keyboard.GetState();
        private bool inPlay = false;
        private bool inMenu = true;
        private bool inHelp = false;
        private bool inVictory = false;
        private bool inPause = false;
        private bool inDraw = false;

        private bool updatesAfterVictory = true;

        public FourBall()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferHeight = 880;
            graphics.PreferredBackBufferWidth = 1150;

            graphics.PreferMultiSampling = true;
            Content.RootDirectory = "Content";
        }


        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Creare un nuovo SpriteBatch, che potrà essere utilizzato per disegnare trame.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            font = Content.Load<SpriteFont>("font");

            back = Content.Load<Texture2D>("back");
            rear = Content.Load<Texture2D>("rear");
            menu = Content.Load<Texture2D>("menu");
            help = Content.Load<Texture2D>("help");
            pause = Content.Load<Texture2D>("pause");

            orangew = Content.Load<Texture2D>("orangew");
            cyanw = Content.Load<Texture2D>("cyanw");

            hl = Content.Load<Texture2D>("highligth");
            blue = Content.Load<Texture2D>("blue");
            red = Content.Load<Texture2D>("red");
            gold = Content.Load<Texture2D>("gold");

            draw = Content.Load<Texture2D>("draw");

            menuSel = Content.Load<Texture2D>("menusel");

            menuSound = Content.Load<SoundEffect>("menuSound");
            backSound = Content.Load<SoundEffect>("back_sound");

            pushButton = Content.Load<SoundEffect>("pushButton");
            exitZone = Content.Load<SoundEffect>("exitZone");

            applause = Content.Load<SoundEffect>("applause");

            backSoundInstance = backSound.CreateInstance();
            backSoundInstance.IsLooped = true;
            backSoundInstance.Play();
            
            selectClmSound = Content.Load<SoundEffect>("selection");
            shootSound = Content.Load<SoundEffect>("shoot");
            bounceSound = Content.Load<SoundEffect>("bounce");

            cubeModel = Content.Load<Model>("cube_001");
            cube = new MyModel(cubeModel, new Vector3(0.5f, -3.8f, 0.45f), new Vector3(0.01f, 0.01f, 0.0f), new Vector3(0.5f, 0.5f, 0.5f), GraphicsDevice);

            FourBallState.clearState(this.GraphicsDevice.Viewport.Height, red.Height);
        }

        void draw3dCube()
        {
            cube.Rotation += new Vector3(0.01f, 0.01f, 0.01f);
            cube.Draw(Matrix.CreateLookAt(
                    cameraPosition,
                    Vector3.Zero,
                    Vector3.Up),
                Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.ToRadians(45.0f),
                    (float)1150 / (float)880,
                    1.0f,
                    10000.0f));
        }
  
        protected override void Update(GameTime gameTime)
        {
            KeyboardState n = Keyboard.GetState();
            if (n.IsKeyDown(Keys.Q) && k.IsKeyUp(Keys.Q))
            {
                foreach (var b in FourBallState.game_state.BoardMatrix.Value)
                {
                    Console.Write(b + " ");
                }
                Console.WriteLine();
            }
            if (n.IsKeyDown(Keys.W) && k.IsKeyUp(Keys.W))
            {
                FourBallState.game_state.BoardMatrix.Value[0] = -1;
                FourBallState.Ball myball = new FourBallState.Ball(new Casanova.Variable<double>(55.0,55.0),
                                                                   new Casanova.Variable<double>(0.0,0),
                                                                   new Casanova.Variable<double>(0,0),
                                                                   new Casanova.Variable<double>(0, 0), 
                                                                   new Microsoft.FSharp.Core.FSharpRef<bool>(false), 
                                                                   -1, 0, 0);
                
                FourBallState.game_state.BallArray.Value[0] = myball;
            }

            if (inPlay)
            {
                bool checkActiveBall = true;
                foreach (var b in FourBallState.game_state.BallArray.Value)
                {
                    if (b.Active.Value == true)
                        checkActiveBall = false;
                }

                if (FourBallState.victory.Value != 0)
                    inVictory = true;

                if (FourBallState.totalBall.Value == 0)
                    inDraw = true;

                if (checkActiveBall && inDraw && !inPause)
                {
                    if (n.IsKeyDown(Keys.Escape) && k.IsKeyUp(Keys.Escape))
                    {
                        inMenu = true;
                        inHelp = false;
                        inPlay = false;
                        inPause = false;
                        inVictory = false;

                        FourBallState.victory.Value = 0;
                        FourBallState.totalBall.Value = FourBallState.numCol * FourBallState.numRow;
                        exitZone.Play();
                    }

                    if (n.IsKeyDown(Keys.P) && k.IsKeyUp(Keys.P))
                    {
                        inMenu = false;
                        inHelp = false;
                        inPlay = true;
                        inPause = false;
                        inVictory = false;
                        inDraw = false;

                        FourBallState.clearState(this.GraphicsDevice.Viewport.Height, red.Height);
                        FourBallState.victory.Value = 0;
                        
                        FourBallState.totalBall.Value = FourBallState.numCol * FourBallState.numRow;
                        exitZone.Play();
                    }
                }

                else if (checkActiveBall && inVictory && !inPause)
                {
                    if (updatesAfterVictory)
                    {
                        applause.Play();
                        
                        if (FourBallState.victory.Value == 1)
                            ++FourBallState.player_one.Score.Value;
                        else if (FourBallState.victory.Value == -1)
                            ++FourBallState.player_two.Score.Value;

                        updatesAfterVictory = false;
                    }
                    if (n.IsKeyDown(Keys.Escape) && k.IsKeyUp(Keys.Escape))
                    {
                        inMenu = true;
                        inHelp = false;
                        inPlay = false;
                        inPause = false;
                        inVictory = false;

                        updatesAfterVictory = true;

                        FourBallState.victory.Value = 0;
                        FourBallState.totalBall.Value = FourBallState.numCol * FourBallState.numRow;
                        exitZone.Play();
                    }

                    if (n.IsKeyDown(Keys.P) && k.IsKeyUp(Keys.P))
                    {
                        inMenu = false;
                        inHelp = false;
                        inPlay = true;
                        inPause = false;

                        updatesAfterVictory = true;

                        FourBallState.clearState(this.GraphicsDevice.Viewport.Height, red.Height);
                        FourBallState.victory.Value = 0;
                        inVictory = false;
                        FourBallState.totalBall.Value = FourBallState.numCol * FourBallState.numRow;
                        exitZone.Play();
                    }
                }
                else if (!inVictory && inPause)
                {
                    if (n.IsKeyDown(Keys.P) && k.IsKeyUp(Keys.P))
                    {
                        inMenu = false;
                        inHelp = false;
                        inPlay = true;
                        inPause = false;

                        exitZone.Play();
                    }
                }
                else
                {
                    FourBallState.update_state();
                    FourBallState.update_script();
                    Casanova.commit_variable_updates();

                    if (FourBallState.selection)
                    {
                        selectClmSound.Play();
                        FourBallState.selection = false;
                    }
                    if (FourBallState.shoot)
                    {
                        shootSound.Play();
                        FourBallState.shoot = false;
                    }
                    if (FourBallState.bounce)
                    {
                        bounceSound.Play();
                        FourBallState.bounce = false;
                    }

                    if (n.IsKeyDown(Keys.Escape) && k.IsKeyUp(Keys.Escape))
                    {
                        inMenu = true;
                        inPlay = false;
                        inHelp = false;

                        exitZone.Play();
                    }
                    if (n.IsKeyDown(Keys.P) && k.IsKeyUp(Keys.P))
                    {
                        inMenu = false;
                        inHelp = false;
                        inPlay = true;
                        inPause = true;
                    }
                }
            }

            if (inMenu)
            {
                if (n.IsKeyDown(Keys.Up) && k.IsKeyUp(Keys.Up))
                {
                    posMenuSel -= new Vector2(0, 75);
                    if (posMenuSel.Y < 375)
                        posMenuSel.Y = 375 + 2 * 75;

                    --menuItem;
                    if (menuItem < 0)
                        menuItem = 2;

                    menuSound.Play();
                }

                if (n.IsKeyDown(Keys.Down) && k.IsKeyUp(Keys.Down))
                {
                    posMenuSel += new Vector2(0, 75);
                    if (posMenuSel.Y > (375 + 2 * 75))
                        posMenuSel.Y = 375;

                    ++menuItem;
                    if (menuItem > 2)
                        menuItem = 0;

                    menuSound.Play();
                }

                if (n.IsKeyDown(Keys.Enter) && k.IsKeyUp(Keys.Enter))
                {
                    if (menuItem == 0)
                    {
                        inMenu = false;
                        inPlay = true;

                        FourBallState.clearState(this.GraphicsDevice.Viewport.Height, red.Height);
                        FourBallState.player_one.Score.Value = 0;
                        FourBallState.player_two.Score.Value = 0;
                        FourBallState.totalBall.Value = FourBallState.numCol * FourBallState.numRow;
                    }

                    else if (menuItem == 1)
                    {
                        inMenu = false;
                        inHelp = true;
                    }

                    else if (menuItem == 2)
                    {
                        this.Exit();
                    }

                    pushButton.Play();
                }
            }

            if (inHelp)
            {
                if (n.IsKeyDown(Keys.Escape) && k.IsKeyUp(Keys.Escape))
                {
                    inMenu = true;
                    inPlay = false;
                    inHelp = false;

                    exitZone.Play();
                }
            }

            k = n;
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.DarkGreen);

            spriteBatch.Begin();
            spriteBatch.Draw(rear, Vector2.Zero, Color.White);

            if (inPlay)
            {   
                spriteBatch.Draw(back, new Vector2(10, 10), Color.White);
                spriteBatch.DrawString(font,
                    FourBallState.player_one.Score.Value.ToString() + 
                    "                                                 " + 
                    FourBallState.player_two.Score.Value.ToString(),
                    new Vector2(400, 55), Color.Black);
                spriteBatch.Draw(hl, new Vector2(135 + 120 * FourBallState.game_state.col.Value, 70), Color.White);
                foreach (var b in FourBallState.game_state.BallArray.Value)
                {
                    if (b.Player == -1)
                        spriteBatch.Draw(blue, new Vector2((float)(140 + 120 * b.Col), (float)(70 - b.Position.Value)), Color.White);
                    else if (b.Player == 1)
                        spriteBatch.Draw(red, new Vector2((float)(140 + 120 * b.Col), (float)(70 - b.Position.Value)), Color.White);
                }

                if (inPause)
                {
                    spriteBatch.Draw(pause, Vector2.Zero, Color.White);
                }

                if (FourBallState.totalBall.Value == 0)
                {
                    bool check = true;
                    foreach (var b in FourBallState.game_state.BallArray.Value)
                    {
                        if (b.Active.Value == true)
                            check = false;
                    }

                    if (check)
                        spriteBatch.Draw(draw, Vector2.Zero, Color.White);
                }

                if (FourBallState.victory.Value == -1)
                {
                    bool check = true;
                    foreach (var b in FourBallState.game_state.BallArray.Value)
                    {
                        if (b.Active.Value == true)
                            check = false;
                    }

                    if(check)
                        spriteBatch.Draw(cyanw, Vector2.Zero, Color.White);
                }
                else if (FourBallState.victory.Value == 1)
                {
                    bool check = true;
                    foreach (var b in FourBallState.game_state.BallArray.Value)
                    {
                        if (b.Active.Value == true)
                            check = false;
                    }

                    if (check)
                        spriteBatch.Draw(orangew, Vector2.Zero, Color.White);
                }

                draw3dCube();
            }

            if (inMenu)
            {
                spriteBatch.Draw(menu, new Vector2(10, 10), Color.White);
                spriteBatch.Draw(menuSel, posMenuSel, Color.White);
            }

            if (inHelp)
            {
                spriteBatch.Draw(help, new Vector2(10, 10), Color.White);
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
